#ifndef QSERIALBASE_H
#define QSERIALBASE_H
#define _TTY_WIN_
#include <QIODevice>
#include <QFile>
#include <QThread>
#include <QMutex>

/*macros for thread support*/
#define LOCK_MUTEX() m_pMutex->lock()
#define UNLOCK_MUTEX() m_pMutex->unlock()

/*line status constants*/
#define LS_CTS  0x01
#define LS_DSR  0x02
#define LS_DCD  0x04
#define LS_RI   0x08
#define LS_RTS  0x10
#define LS_DTR  0x20
#define LS_ST   0x40
#define LS_SR   0x80

/*error constants*/
#define E_NO_ERROR                   0
#define E_INVALID_FD                 1
#define E_NO_MEMORY                  2
#define E_CAUGHT_NON_BLOCKED_SIGNAL  3
#define E_PORT_TIMEOUT               4
#define E_INVALID_DEVICE             5
#define E_BREAK_CONDITION            6
#define E_FRAMING_ERROR              7
#define E_IO_ERROR                   8
#define E_BUFFER_OVERRUN             9
#define E_RECEIVE_OVERFLOW          10
#define E_RECEIVE_PARITY_ERROR      11
#define E_TRANSMIT_OVERFLOW         12
#define E_READ_FAILED               13
#define E_WRITE_FAILED              14

/*!
 * Enums for port settings.
 */
enum NamingConvention
{
    WIN_NAMES,
    IRIX_NAMES,
    HPUX_NAMES,
    SUN_NAMES,
    DIGITAL_NAMES,
    FREEBSD_NAMES,
    LINUX_NAMES
};

enum BaudRateType
{
    BAUD50,                //POSIX ONLY
    BAUD75,                //POSIX ONLY
    BAUD110,
    BAUD134,               //POSIX ONLY
    BAUD150,               //POSIX ONLY
    BAUD200,               //POSIX ONLY
    BAUD300,
    BAUD600,
    BAUD1200,
    BAUD1800,              //POSIX ONLY
    BAUD2400,
    BAUD4800,
    BAUD9600,
    BAUD14400,             //WINDOWS ONLY
    BAUD19200,
    BAUD38400,
    BAUD56000,             //WINDOWS ONLY
    BAUD57600,
    BAUD76800,             //POSIX ONLY
    BAUD115200,
    BAUD128000,            //WINDOWS ONLY
    BAUD256000             //WINDOWS ONLY
};

enum DataBitsType
{
    DATA_5,
    DATA_6,
    DATA_7,
    DATA_8
};

enum ParityType
{
    PAR_NONE,
    PAR_ODD,
    PAR_EVEN,
    PAR_MARK,               //WINDOWS ONLY
    PAR_SPACE
};

enum StopBitsType
{
    STOP_1,
    STOP_1_5,               //WINDOWS ONLY
    STOP_2
};

enum FlowType
{
    FLOW_OFF,
    FLOW_HARDWARE,
    FLOW_XONXOFF
};

/**
 * structure to contain port settings
 */
struct PortSettings
{
    BaudRateType BaudRate;
    DataBitsType DataBits;
    ParityType Parity;
    StopBitsType StopBits;
    FlowType FlowControl;
    long Timeout_Millisec;
};



class QSerialBase: public QIODevice
{
    Q_OBJECT
public:
    enum QueryMode {
        Polling,
        EventDriven
    };
public:
    QSerialBase();
    QSerialBase(int iPort);
    virtual ~QSerialBase();

    void    SetSerialName(int   iPort);
    QString SerialName();


public:
    virtual void construct();
    virtual void setQueryMode(QueryMode mode);
    virtual BaudRateType baudRate() const;
    virtual DataBitsType dataBits() const;
    virtual ParityType parity() const;
    virtual StopBitsType stopBits() const;
    virtual FlowType flowControl() const;

    virtual bool isSequential() const;

    virtual bool atEnd() const;

    virtual qint64 readLine(char * data, qint64 maxSize);

    virtual ulong lastError() const;


    virtual void setBaudRate(BaudRateType)=0;
    virtual void setDataBits(DataBitsType)=0;
    virtual void setParity(ParityType)=0;
    virtual void setStopBits(StopBitsType)=0;
    virtual void setFlowControl(FlowType)=0;
    virtual void setTimeout(long)=0;
    virtual bool open(OpenMode mode)=0;
    virtual void close()=0;
    virtual void flush()=0;
    virtual qint64 size() const=0;
    virtual qint64 bytesAvailable()=0;
    virtual void translateError(ulong error)=0;
    virtual void setDtr(bool set=true)=0;
    virtual void setRts(bool set=true)=0;
    virtual ulong lineStatus()=0;

protected:
    virtual qint64 readData(char * data, qint64 maxSize)=0;
    virtual qint64 writeData(const char * data, qint64 maxSize)=0;

protected:
    QMutex*         m_pMutex;
    PortSettings    m_PortSettings;
    ulong           m_ulLastErr;
    QSerialBase::QueryMode _queryMode;
    QString         m_strSerialName;

public:
    QSerialBase::QueryMode queryMode() const { return _queryMode; }

signals:
    void dsrChanged(bool status);
};

#endif // QSERIALBASE_H
